package com.mulong.mall.service.impl;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mulong.common.client.AliyunOssClient;
import com.mulong.common.dao.mall.ChannelDao;
import com.mulong.common.domain.pojo.mall.custom.CustomSupplierChannelDeliveryCharge;
import com.mulong.common.domain.pojo.mall.custom.CustomSupplierChannelDiscount;
import com.mulong.common.domain.pojo.mall.custom.CustomSupplierChannelSkuDiscount;
import com.mulong.common.domain.pojo.mall.custom.SupplierChannelDeliveryChargeQuery;
import com.mulong.common.domain.pojo.mall.custom.SupplierChannelDiscountQuery;
import com.mulong.common.domain.pojo.mall.custom.SupplierChannelQuery;
import com.mulong.common.domain.pojo.mall.custom.SupplierChannelSkuDiscountQuery;
import com.mulong.common.exception.ErrorEnums;
import com.mulong.common.exception.MulongException;
import com.mulong.common.util.MulongUtil;
import com.mulong.mall.constants.Constants;
import com.mulong.mall.domain.bo.manager.*;
import com.mulong.mall.domain.param.manager.*;
import com.mulong.mall.domain.result.manager.*;
import com.mulong.mall.service.ManagerChannelService;
import com.mulong.mall.service.support.ManagerChannelSupport;
import com.mulong.mall.util.MallRequestContext;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * ManagerChannelServiceImpl
 * 
 * @author mulong
 * @data 2021-06-21 14:09:31
 */
@Slf4j
@Service
public class ManagerChannelServiceImpl implements ManagerChannelService {
    @Autowired
    private ChannelDao channelDao;
    @Autowired
    private ManagerChannelSupport managerChannelSupport;
    @Autowired
    private AliyunOssClient aliyunOssClient;

    /**
     * 查询渠道
     * 
     * @author mulong
     */
    @Override
    public GetChannelSupplierByPageResult getSupplierByPage(GetChannelSupplierByPageParam param) {
        SupplierChannelQuery query = new SupplierChannelQuery();
        query.setNameKeyword(param.getNameKeyword());
        query.setOrderBy("`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<com.mulong.common.domain.pojo.mall.SupplierChannel> page = (Page<com.mulong.common.domain.pojo.mall.SupplierChannel>) channelDao.query(query);
        GetChannelSupplierByPageResult getChannelByPageResult = new GetChannelSupplierByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<com.mulong.common.domain.pojo.mall.SupplierChannel> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getChannelByPageResult.setResult(list.stream().map(ChannelSupplier::new).collect(Collectors.toList()));
        }
        return getChannelByPageResult;
    }

    /**
     * 添加渠道
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplier addSupplier(ChannelSupplier supplier) {
        supplier.setId(null);
        com.mulong.common.domain.pojo.mall.SupplierChannel newRecord = supplier.buildSupplierChannel();
        newRecord = channelDao.add(newRecord, MallRequestContext.getUsername());
        return new ChannelSupplier(newRecord);
    }

    /**
     * 查询渠道
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplier getSupplierById(Integer id) {
        com.mulong.common.domain.pojo.mall.SupplierChannel record = channelDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new ChannelSupplier(record);
    }

    /**
     * 更新渠道
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplier putSupplierById(Integer id, ChannelSupplier supplier) {
        if (!id.equals(supplier.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannel record = channelDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannel newRecord = supplier.buildSupplierChannel();
        record.setName(newRecord.getName());
        record.setShortName(newRecord.getShortName());
        record.setDescription(newRecord.getDescription());
        record.setRelatedGatewayAccountId(newRecord.getRelatedGatewayAccountId());
        record.setInventoryUpdateTime(newRecord.getInventoryUpdateTime());
        record.setInventoryUpdateRemark(newRecord.getInventoryUpdateRemark());
        channelDao.put(record, MallRequestContext.getUsername());
        return new ChannelSupplier(record);
    }

    /**
     * 删除渠道
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplier deleteSupplierById(Integer id) {
        com.mulong.common.domain.pojo.mall.SupplierChannel record = channelDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        channelDao.delete(record, MallRequestContext.getUsername());
        return new ChannelSupplier(record);
    }

    /**
     * 查询渠道折扣
     * 
     * @author mulong
     */
    @Override
    public GetChannelSupplierDiscountByPageResult getSupplierDiscountByPage(GetChannelSupplierDiscountByPageParam param) {
        SupplierChannelDiscountQuery query = new SupplierChannelDiscountQuery();
        query.setChannelId(param.getChannelId());
        query.setBrandId(param.getBrandId());
        query.setGoodsCategory(param.getGoodsCategory());
        query.setOrderBy("scd.`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<CustomSupplierChannelDiscount> page = (Page<CustomSupplierChannelDiscount>) channelDao.queryDiscount(query);
        GetChannelSupplierDiscountByPageResult getChannelDiscountByPageResult = new GetChannelSupplierDiscountByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<CustomSupplierChannelDiscount> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getChannelDiscountByPageResult.setResult(list.stream().map(ChannelSupplierDiscount::new).collect(Collectors.toList()));
        }
        return getChannelDiscountByPageResult;
    }

    /**
     * 添加渠道折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDiscount addSupplierDiscount(ChannelSupplierDiscount supplierDiscount) {
        supplierDiscount.setId(null);
        com.mulong.common.domain.pojo.mall.SupplierChannelDiscount newRecord = supplierDiscount.buildSupplierChannelDiscount();
        newRecord = channelDao.addDiscount(newRecord, MallRequestContext.getUsername());
        return new ChannelSupplierDiscount(newRecord);
    }

    /**
     * 查询渠道折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDiscount getSupplierDiscountById(Long id) {
        com.mulong.common.domain.pojo.mall.SupplierChannelDiscount record = channelDao.queryDiscountById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new ChannelSupplierDiscount(record);
    }

    /**
     * 更新渠道折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDiscount putSupplierDiscountById(Long id, ChannelSupplierDiscount supplierDiscount) {
        if (!id.equals(supplierDiscount.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannelDiscount record = channelDao.queryDiscountById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannelDiscount newRecord = supplierDiscount.buildSupplierChannelDiscount();
        record.setChannelId(newRecord.getChannelId());
        record.setBrandId(newRecord.getBrandId());
        record.setGoodsCategory(newRecord.getGoodsCategory());
        record.setDiscount(newRecord.getDiscount());
        channelDao.putDiscount(record, MallRequestContext.getUsername());
        return new ChannelSupplierDiscount(record);
    }

    /**
     * 删除渠道折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDiscount deleteSupplierDiscountById(Long id) {
        com.mulong.common.domain.pojo.mall.SupplierChannelDiscount record = channelDao.queryDiscountById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        channelDao.deleteDiscount(record, MallRequestContext.getUsername());
        return new ChannelSupplierDiscount(record);
    }

    /**
     * 查询渠道货号折扣
     * 
     * @author mulong
     */
    @Override
    public GetChannelSupplierSkuDiscountByPageResult getSupplierSkuDiscountByPage(GetChannelSupplierSkuDiscountByPageParam param) {
        SupplierChannelSkuDiscountQuery query = new SupplierChannelSkuDiscountQuery();
        query.setChannelId(param.getChannelId());
        query.setSku(param.getSku());
        query.setOrderBy("scsd.`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<CustomSupplierChannelSkuDiscount> page = (Page<CustomSupplierChannelSkuDiscount>) channelDao.querySkuDiscount(query);
        GetChannelSupplierSkuDiscountByPageResult getChannelSupplierSkuDiscountByPageResult = new GetChannelSupplierSkuDiscountByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<CustomSupplierChannelSkuDiscount> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getChannelSupplierSkuDiscountByPageResult.setResult(list.stream().map(ChannelSupplierSkuDiscount::new).collect(Collectors.toList()));
        }
        return getChannelSupplierSkuDiscountByPageResult;
    }

    /**
     * 添加渠道货号折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierSkuDiscount addSupplierSkuDiscount(ChannelSupplierSkuDiscount supplierSkuDiscount) {
        supplierSkuDiscount.setId(null);
        com.mulong.common.domain.pojo.mall.SupplierChannelSkuDiscount newRecord = supplierSkuDiscount.buildSupplierChannelSkuDiscount();
        newRecord = channelDao.addSkuDiscount(newRecord, MallRequestContext.getUsername());
        return new ChannelSupplierSkuDiscount(newRecord);
    }

    /**
     * 查询渠道货号折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierSkuDiscount getSupplierSkuDiscountById(Long id) {
        com.mulong.common.domain.pojo.mall.SupplierChannelSkuDiscount record = channelDao.querySkuDiscountById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new ChannelSupplierSkuDiscount(record);
    }

    /**
     * 更新渠道货号折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierSkuDiscount putSupplierSkuDiscountById(Long id, ChannelSupplierSkuDiscount supplierSkuDiscount) {
        if (!id.equals(supplierSkuDiscount.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannelSkuDiscount record = channelDao.querySkuDiscountById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannelSkuDiscount newRecord = supplierSkuDiscount.buildSupplierChannelSkuDiscount();
        record.setChannelId(newRecord.getChannelId());
        record.setSku(newRecord.getSku());
        record.setDiscount(newRecord.getDiscount());
        channelDao.putSkuDiscount(record, MallRequestContext.getUsername());
        return new ChannelSupplierSkuDiscount(record);
    }

    /**
     * 删除渠道货号折扣
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierSkuDiscount deleteSupplierSkuDiscountById(Long id) {
        com.mulong.common.domain.pojo.mall.SupplierChannelSkuDiscount record = channelDao.querySkuDiscountById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        channelDao.deleteSkuDiscount(record, MallRequestContext.getUsername());
        return new ChannelSupplierSkuDiscount(record);
    }

    /**
     * 下载渠道货号折扣
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadSupplierSkuDiscount(DownloadSupplierSkuDiscountParam param) {
        String fileName = Constants.MANAGER_DOWNLOAD_SUPPLIER_SKU_DISCOUNT_FILENAME;
        // get data
        SupplierChannelSkuDiscountQuery query = new SupplierChannelSkuDiscountQuery();
        query.setChannelId(param.getChannelId());
        query.setSku(param.getSku());
        query.setOrderBy("scsd.`update_time` DESC");
        List<com.mulong.common.domain.pojo.mall.custom.CustomSupplierChannelSkuDiscount> records = channelDao.querySkuDiscount(query);
        // build content
        byte[] content = null;
        try (HSSFWorkbook workbook = new HSSFWorkbook()) {
            HSSFSheet sheet = workbook.createSheet(Constants.MANAGER_DOWNLOAD_SUPPLIER_SKU_DISCOUNT_SHEET_NAME);            
            List<String> titles = Constants.MANAGER_DOWNLOAD_SUPPLIER_SKU_DISCOUNT_SHEET_TITLE;
            MulongUtil.addTitle(workbook, sheet, titles);
            HSSFCellStyle defaultStyle = MulongUtil.getDefaultCellStyle(workbook);
            int lastRowNum = sheet.getLastRowNum();
            for (int j = 0; j < records.size(); j++) {
                com.mulong.common.domain.pojo.mall.custom.CustomSupplierChannelSkuDiscount record = records.get(j);
                HSSFRow row = sheet.createRow(j + (lastRowNum + 1));
                managerChannelSupport.addRow(row, record, defaultStyle);
            }
            content = MulongUtil.toByteArray(workbook);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("导出数据异常"));
        }
        // build response
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 上传渠道货号折扣
     * 
     * @author mulong
     */
    @Override
    public UploadSupplierSkuDiscountResult uploadSupplierSkuDiscount(MultipartFile file) {
        if (file.isEmpty()) {
            log.error("upload file is empty");
            throw new MulongException(ErrorEnums.UPLOAD_FILE_EMPTY);
        }
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream, Constants.MANAGER_UPLOAD_SUPPLIER_SKU_DISCOUNT_SHEET_NAME);
            List<UploadSupplierSkuDiscountRecord> records = managerChannelSupport.buildUploadSupplierSkuDiscountRecordList(reader);
            reader.close();
            if (!CollectionUtils.isEmpty(records)) {
                managerChannelSupport.insertSupplierSkuDiscount(records);
            }
            UploadSupplierSkuDiscountResult uploadSupplierSkuDiscountResult = new UploadSupplierSkuDiscountResult();
            uploadSupplierSkuDiscountResult.setSupplierSkuDiscountCount(records.size());
            return uploadSupplierSkuDiscountResult;
        } catch (MulongException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.UPLOAD_FILE_SERVER_ERROR);
        }
    }

    /**
     * 下载渠道货号折扣模板
     * 
     * @author mulong
     */
    @Override
    public ResponseEntity<byte[]> downloadSupplierSkuDiscountTemplate() {
        String fileName = Constants.MANAGER_UPLOAD_SUPPLIER_CHANNEL_SKY_DISCOUNT_TEMPLATE_FILENAME;
        String ossKey = Constants.MANAGER_UPLOAD_SUPPLIER_CHANNEL_SKY_DISCOUNT_TEMPLATE_OSS_KEY;
        byte[] content = null;
        try {
            content = aliyunOssClient.downloadToByteArray(ossKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            content = null;
        }
        if (content == null) {
            throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format("下载模板异常"));
        }
        return MulongUtil.buildDownloadResponse("application/octet-stream", fileName, content);
    }

    /**
     * 查询渠道邮费
     * 
     * @author mulong
     */
    @Override
    public GetChannelSupplierDeliveryChargeByPageResult getSupplierDeliveryChargeByPage(GetChannelSupplierDeliveryChargeByPageParam param) {
        SupplierChannelDeliveryChargeQuery query = new SupplierChannelDeliveryChargeQuery();
        query.setChannelId(param.getChannelId());
        query.setDeliveryTypeId(param.getDeliveryTypeId());
        query.setProvince(param.getProvince());
        query.setOrderBy("scdc.`update_time` DESC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<CustomSupplierChannelDeliveryCharge> page = (Page<CustomSupplierChannelDeliveryCharge>) channelDao.queryDeliveryCharge(query);
        GetChannelSupplierDeliveryChargeByPageResult getChannelExpressChargeByPageResult = new GetChannelSupplierDeliveryChargeByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<CustomSupplierChannelDeliveryCharge> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getChannelExpressChargeByPageResult.setResult(list.stream().map(ChannelSupplierDeliveryCharge::new).collect(Collectors.toList()));
        }
        return getChannelExpressChargeByPageResult;
    }

    /**
     * 添加渠道邮费
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDeliveryCharge addSupplierDeliveryCharge(ChannelSupplierDeliveryCharge supplierDeliveryCharge) {
        supplierDeliveryCharge.setId(null);
        com.mulong.common.domain.pojo.mall.SupplierChannelDeliveryCharge newRecord = supplierDeliveryCharge.buildSupplierChannelDeliveryCharge();
        if (newRecord.getChannelId() < 0) {
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        newRecord = channelDao.addDeliveryCharge(newRecord, MallRequestContext.getUsername());
        return new ChannelSupplierDeliveryCharge(newRecord);
    }

    /**
     * 查询渠道邮费
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDeliveryCharge getSupplierDeliveryChargeById(Long id) {
        com.mulong.common.domain.pojo.mall.SupplierChannelDeliveryCharge record = channelDao.queryDeliveryChargeById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new ChannelSupplierDeliveryCharge(record);
    }

    /**
     * 更新渠道邮费
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDeliveryCharge putSupplierDeliveryChargeById(Long id, ChannelSupplierDeliveryCharge supplierDeliveryCharge) {
        if (!id.equals(supplierDeliveryCharge.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        if (supplierDeliveryCharge.getChannelId() < 0) {
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannelDeliveryCharge record = channelDao.queryDeliveryChargeById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.SupplierChannelDeliveryCharge newRecord = supplierDeliveryCharge.buildSupplierChannelDeliveryCharge();
        record.setChannelId(newRecord.getChannelId());
        record.setDeliveryTypeId(newRecord.getDeliveryTypeId());
        record.setProvince(newRecord.getProvince());
        record.setFirstPrice(newRecord.getFirstPrice());
        record.setAddPrice(newRecord.getAddPrice());
        channelDao.putDeliveryCharge(record, MallRequestContext.getUsername());
        return new ChannelSupplierDeliveryCharge(record);
    }

    /**
     * 删除渠道邮费
     * 
     * @author mulong 
     */
    @Override
    public ChannelSupplierDeliveryCharge deleteSupplierDeliveryChargeById(Long id) {
        com.mulong.common.domain.pojo.mall.SupplierChannelDeliveryCharge record = channelDao.queryDeliveryChargeById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        channelDao.deleteDeliveryCharge(record, MallRequestContext.getUsername());
        return new ChannelSupplierDeliveryCharge(record);
    }

}
